package org.hhf.core;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * RedisCore类是nano-redis的核心组件，管理所有键值对和过期时间
 */
public class RedisCore {
    // 存储所有键值对
    private final ConcurrentHashMap<String, Object> data;
    // 存储键的过期时间
    private final ConcurrentHashMap<String, Long> expireTimes;
    // 存储数据类型
    private final ConcurrentHashMap<String, DataType> dataTypes;

    public RedisCore() {
        data = new ConcurrentHashMap<>();
        expireTimes = new ConcurrentHashMap<>();
        dataTypes = new ConcurrentHashMap<>();
    }

    /**
     * 检查键是否已过期
     */
    private boolean isExpired(String key) {
        if (!expireTimes.containsKey(key)) {
            return false;
        }
        long expireTime = expireTimes.get(key);
        if (expireTime < System.currentTimeMillis()) {
            // 键已过期，删除它
            remove(key);
            return true;
        }
        return false;
    }

    /**
     * 获取键对应的值
     */
    public Object get(String key) {
        if (isExpired(key)) {
            return null;
        }
        return data.get(key);
    }

    /**
     * 设置键值对
     */
    public void put(String key, Object value, DataType type) {
        data.put(key, value);
        dataTypes.put(key, type);
    }

    /**
     * 检查键是否存在
     */
    public boolean exists(String key) {
        if (isExpired(key)) {
            return false;
        }
        return data.containsKey(key);
    }

    /**
     * 删除键
     */
    public void remove(String key) {
        data.remove(key);
        expireTimes.remove(key);
        dataTypes.remove(key);
    }

    /**
     * 设置键的过期时间
     */
    public void expire(String key, long seconds) {
        if (!data.containsKey(key)) {
            return;
        }
        long expireTime = System.currentTimeMillis() + seconds * 1000;
        expireTimes.put(key, expireTime);
    }

    /**
     * 设置键的过期时间（绝对时间）
     */
    public void expireAt(String key, long timestamp) {
        if (!data.containsKey(key)) {
            return;
        }
        expireTimes.put(key, timestamp);
    }

    /**
     * 获取键的剩余生存时间
     */
    public long ttl(String key) {
        if (isExpired(key)) {
            return -2; // 键不存在
        }
        if (!expireTimes.containsKey(key)) {
            return -1; // 键存在但没有过期时间
        }
        long remainingTime = (expireTimes.get(key) - System.currentTimeMillis()) / 1000;
        return Math.max(0, remainingTime);
    }

    /**
     * 获取数据类型
     */
    public DataType getType(String key) {
        if (isExpired(key)) {
            return null;
        }
        return dataTypes.get(key);
    }

    /**
     * 获取所有键
     */
    public Set<String> keys() {
        // 先清理过期键
        for (String key : new HashSet<>(data.keySet())) {
            isExpired(key);
        }
        return new HashSet<>(data.keySet());
    }

    /**
     * 数据类型枚举
     */
    public enum DataType {
        STRING, LIST, SET, HASH, ZSET
    }
}